<?php
// +----------------------------------------------------------------------
// | OpenSociax [ open your team ! ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://www.sociax.com.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: genixsoft.net <智士软件>
// +----------------------------------------------------------------------
// $Id$

class HighlighterService extends Service {
	protected $allowedposttags = array();
	protected $allowedTags = array();
	protected $syntax_token ='';
	protected $syntax_matches = array();
	
	
	public function run(){}
	
	public function __construct(){
				vendor('libs.geshi.geshi');
			  $this->allowedposttags['code'] = array(
			    'lang' => array(),
			    'line' => array(),
			    'escaped' => array(),
			    'style' => array(),
			    'width' => array(),
			  );
			  //Allow plugin use in comments
			  $this->allowedtags['code'] = array(
			    'lang' => array(),
			    'line' => array(),
			    'escaped' => array(),
			  );
			  $this->syntax_token =  md5(uniqid(rand()));
	}

	public function syntax_code_trim($code) {
		// special ltrim b/c leading whitespace matters on 1st line of content
		$code = preg_replace ( "/\<br \/>/siU", "\n\r", $code );
		$code = preg_replace ( "/^\s*\n/siU", "", $code );
		$code = rtrim ( $code );
		return $code;
	}
	
	
	public function syntax_substitute(&$match) {
		$i = count ( $this->syntax_matches );
		$this->syntax_matches [$i] = $match;
		return "\n\n<p>" . $this->syntax_token . sprintf ( "%03d", $i ) . "</p>\n\n";
	}
	
	public function syntax_line_numbers($code, $start) {
		$line_count = count ( explode ( "\n", $code ) );
		$output = "<div>";
		for($i = 0; $i < $line_count; $i ++) {
			$output .= "<span class='db'>".($start + $i) . "</span>";
		}
		$output .= "</div>";
		return $output;
	}
	
	function syntax_highlight($match) {
		$i = intval ( $match [1] );
		$match = $this->syntax_matches [$i];
		$language = strtolower ( trim ( $match [1] ) );
		$line = trim ( $match [2] );
		$escaped = trim ( $match [3] );
		$code = $this->syntax_code_trim ( $match [4] );
		$code = htmlspecialchars_decode($code);
		
		$geshi = new GeSHi ( $code, $language );
		$geshi->enable_keyword_links ( false );
		$geshi->set_header_type(GESHI_HEADER_DIV);
		if($language == "sql"){
			$caps_modifier = GESHI_CAPS_NO_CHANGE;
		}else{
			$caps_modifier = GESHI_CAPS_LOWER;
		}
		$geshi->set_case_keywords($caps_modifier);
		
		$output .= '<div class="syntaxTitle">'.$language.'代码</div><div class="syntaxBody">';
		$output .= $geshi->parse_code ();
		$output .= '</div>';
		return $output;
	}
	
	public function syntax_before_filter($content) {
		//$content = str_replace('&nbsp;','',$content);
		return preg_replace_callback ( "/\s*\[code(?:lang=[\"']([\w-]+)[\"']|line=[\"'](\d*)[\"']|escaped=[\"'](true|false)?[\"']|\s)+\](.*)\[\/code\]\s*/siU", array($this,'syntax_substitute'), $content );
	}
	
	public function syntax_after_filter($content) {
		$content = preg_replace_callback ( "/<p>\s*" . $this->syntax_token  . "(\d{3})\s*<\/p>/si", array($this,"syntax_highlight"), $content );
		
		return $content;
	}
	
	public function syntax($content){
		$source = $this->syntax_before_filter($content);
		return $this->syntax_after_filter($source);
	}
}
?>